-module(vendor_inst).
-include("rec_dec.hrl").
-behaviour(gen_server).
-export([start/1,init/1,handle_call/3,handle_cast/2,handle_info/2,terminate/2,code_change/3]).

-define(SERVER    , ?MODULE).

start(Vendor) when is_record(Vendor, vendor_rec) ->
	case gen_server:start({local, list_to_atom(lists:flatten([atom_to_list(?SERVER),binary_to_list(Vendor#vendor_rec.id)]))}, ?MODULE, [Vendor], []) of 
	{ok,Pid} ->
		gen_server:call(Pid,refresh),
		Pid;
	{error,Reason} ->
		io:format("start biz_queue service failure with ~p~n",[Reason]),
		undefined
	end.

init([Vendor]) ->
	Qs = lists:map(fun(E) ->
						{E#queue_rec.id,undefined,E}
					end,
					queue_service:get({vendor_id,Vendor#vendor_rec.id})),
	{ok,{Vendor,Qs}}.

handle_call(refresh,_,{Vendor,Qs}) ->
	{reply,ok,
		{Vendor,refresh_queue(Qs)}
	};
	
handle_call(reset,_,{Vendor,Qs}) ->
	io:format("reset cmd received~n"),
	{reply,ok,
		{Vendor,refresh_queue(stop_all_queue(Qs))}
	};
	
handle_call(stop,_,{Vendor,Qs}) ->
	io:format("request to stop~n"),
	{stop,"per request",ok,
		{Vendor,stop_all_queue(Qs)}
	};
handle_call({update_cfg,Cfg},_,{Vendor,Qs}) ->
	{reply,ok,broadcast({update_cfg,{vendor_cfg,Cfg}},{Vendor,Qs})};
handle_call({add,Q},_,{Vendor,Qs}) ->
	{reply,
	ok,
	{Vendor,Qs ++ [{Q#queue_rec.id,start_queue(Q),Q}]}};
handle_call({delete,Q_Id},_,{Vendor,Qs}) ->
	{reply,
		case lists:keyfind(Q_Id,1,Qs) of
		false ->
			error;
		{Q_id,undefined,_} ->
			ok;
		{Q_id,Pid,_} ->
			gen_server:call(Pid,stop),
			ok
		end,
		{Vendor,lists:keydelete(Q_Id,1,Qs)}
	};
handle_call({queue,list},_,{Vendor,Qs}) ->
	{
		reply,
		{ok,
			lists:map(fun({Id,Pid,Q}) ->
					case Pid of
					undefined ->
						#queue_inst_rec{id=Id,name=Q#queue_rec.name};
					Pid ->
						gen_server:call(Pid,{get,queue_info})
					end
				  end,
				  Qs)
		},
		{Vendor,Qs}
	};
	
handle_call({forward_queue_msg,Queue_Id,Msg},_,{Vendor,Qs}) ->
	io:format("forward queue ~p to Queue: ~p ~n",[Msg,Queue_Id]),
	{reply,
		case lists:keyfind(Queue_Id,1,Qs) of
		false ->
			{error,"No Queue Info found"};
		{_,undefined,_} ->
			{error,"Queue is not activated"};
		{Queue_Id,Pid,_} ->
			gen_server:call(Pid,Msg)
		end,
		{Vendor,Qs}};
	
handle_call(ping,_,State) ->
	{reply,ok,State};
	
handle_call(dump,_,State) ->
	io:format("dump Vendor_Inst ~p~n",[State]),
	{reply,ok,State};	
handle_call(_,_,State) ->
	{reply, {error,"no func defined"}, State}.	
handle_cast(_, State) ->
	{noreply,State}.
handle_info(_, State) ->
	{noreply,State}.
terminate(_, _) ->
	ok.
code_change(_, State, _) ->
	{ok,State}.

broadcast(Msg,{Vendor,Qs})->
	lists:foreach(fun({_,Pid,_}) ->
					gen_server:call(Pid,Msg)
					 end,
					 Qs),
	io:format("finish the broadcast Msg:~p~n",[Msg]),
	{Vendor,Qs}.
stop_all_queue(Qs) ->
	lists:map(
		fun({Id,Pid,Q}) ->
			case Pid of
			undefined ->
				{Id,undefined,Q};
			Pid ->
				gen_server:call(Pid,stop),
				{Id,undefined,Q}
			end
		end,
		Qs
	).
refresh_queue(Qs) ->
	lists:map(
		fun({Id,Pid,Q}) ->
			case Pid of
			undefined ->
				{Id,start_queue(Q),Q};
			Pid ->
				{Id,Pid,Q}
			end
		end,
		Qs
	).
start_queue(Q) ->
	queue_inst:start(Q).